/*!
\file Container.cpp
\brief Contains implementation of Container.
\ingroup Algorithm
*/

#include"Container.h" 

#include"Action.h"
#include"ContainerElement.h"

Container::Container(){
	
}

Container::~Container(){
	while( m_container.size() > 0 ){
		delete m_container[0];
		m_container.pop_front();
	}
}

Container::Container( const Container &/*other*/ ):QObject(){
//WARNING: This function should never be called.
}

void Container::push_front( ContainerElement *element ){
	m_container.push_front( element );
	_reportNewElement( element, 0 );
	connect( element, SIGNAL(reportAction(ContainerElementAction*)), this, SLOT(_reportChild(ContainerElementAction*)) );
}

void Container::push_back( ContainerElement *element ){
	m_container.push_back( element );
	_reportNewElement( element, m_container.size()-1 );
	connect( element, SIGNAL(reportAction(ContainerElementAction*)), this, SLOT(_reportChild(ContainerElementAction*)) );
}

void Container::pop_front(){
	m_container[0]->disconnect();
	m_container.pop_front();
	_report( new ContainerElementRemoveAction( 0, 0 ) );
}

void Container::pop_back(){
	m_container[m_container.size()-1]->disconnect();
	m_container.pop_back();
	_report( new ContainerElementRemoveAction( 0, m_container.size()-1 ) );
}

ContainerElement *Container::takeAt(unsigned int i){
	m_container[i]->disconnect();
	ContainerElement *ret = m_container.takeAt(i);
	_report( new ContainerElementRemoveAction(0, i) );
	return ret;
}

void Container::_reportChild( ContainerElementAction *action ){
	QObject *s = sender();
	for( int i = 0; i < m_container.size(); i++ )
		if( m_container[i] == s )
			action->setElement(i);
	_report(action);
}

void Container::_report( ContainerElementAction *action ){
	if( receivers(SIGNAL(reportAction(ContainerElementAction*))) > 0 ){
		emit reportAction(action);
	}else{
		delete action;
	}
}

void Container::_reportNewElement( ContainerElement *element, int seqNum ){
	if(element == 0)
		return;
	if( receivers(SIGNAL(reportAction(ContainerElementAction*))) == 0 ){
		return;
	}
	
	QList<ContainerElementAction*> actions;
	
	actions.push_back( new ContainerElementAddAction( 0, seqNum ) );
// 	_report( new ContainerElementAddAction( 0, seqNum ) );
	
	if( element->node() != 0 ){
		actions.push_back( new ContainerElementSetNodeAction( 0, seqNum, element->node()->identifier(), element->node()->label() ) );
// 		_report( new ContainerElementSetNodeAction( 0, seqNum, element->node()->identifier(), element->node()->label() ) );
	}
	if( element->edge() != 0 ){
		actions.push_back( new ContainerElementSetEdgeAction( 0, seqNum, element->edge()->identifier(), element->edge()->from().identifier(), element->edge()->to().identifier(), element->edge()->label() ) );
// 		_report( new ContainerElementSetEdgeAction( 0, seqNum, element->edge()->identifier(), element->edge()->from().identifier(), element->edge()->to().identifier(), element->edge()->label() ) );
	}
	
	bool dataUsed = false;
	QString data;
	if( element->intUsed() ){
		dataUsed = true;
		data.setNum(element->dataInt());
	}
	
	if( element->doubleUsed() ){
		dataUsed = true;
		if(data.isEmpty())
			data.setNum(element->dataDouble());
		else
			data.append( QString("\n").append(QString().setNum(element->dataDouble())) );
	}
	
	if( element->stringUsed() ){
		dataUsed = true;
		if( data.isEmpty() )
			data = element->dataString();
		else
			data.append( QString("\n").append(element->dataString()) );
	}
	
	if( dataUsed )
		actions.push_back( new ContainerElementSetDataAction( 0, seqNum, data ) );
// 		_report( new ContainerElementSetDataAction( 0, seqNum, data ) );
	while( actions.size() > 0 ){
		if( actions.size() != 1 )
			actions[0]->setUninteresting(true);
		_report( actions.takeAt(0) );
	}
}
